{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# `Table` Usage\n",
    "\n",
    "In this notebook we'll show common `Table` operations using the stock market data introduced in the previous notebook.  `NDSparse` operations are *nearly* identical, so we will focus on `Table`.  The functions we cover here are:\n",
    "\n",
    "1. `select`\n",
    "1. `filter`\n",
    "1. `map`\n",
    "1. `reduce`\n",
    "1. `groupreduce`\n",
    "1. `groupby`\n",
    "1. `summarize`\n",
    "1. `columns`/`rows`\n",
    "1. `join`\n",
    "1. `merge`\n",
    "\n",
    "Each of the above functions has detailed inline documentation, accessed from a Julia REPL with `?select`, for example."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Begin by Loading Data\n",
    "\n",
    "- Let's load the data we saved in the previous notebook:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Table with 56023 rows, 8 columns:\n",
       "\u001b[1mTicker         \u001b[22m\u001b[1mDate        \u001b[22mOpen     High     Low      Close    Volume    OpenInt\n",
       "────────────────────────────────────────────────────────────────────────────────\n",
       "\"aapl.us.txt\"  1984-09-07  0.42388  0.42902  0.41874  0.42388  23220030  0\n",
       "\"aapl.us.txt\"  1984-09-10  0.42388  0.42516  0.41366  0.42134  18022532  0\n",
       "\"aapl.us.txt\"  1984-09-11  0.42516  0.43668  0.42516  0.42902  42498199  0\n",
       "\"aapl.us.txt\"  1984-09-12  0.42902  0.43157  0.41618  0.41618  37125801  0\n",
       "\"aapl.us.txt\"  1984-09-13  0.43927  0.44052  0.43927  0.43927  57822062  0\n",
       "\"aapl.us.txt\"  1984-09-14  0.44052  0.45589  0.44052  0.44566  68847968  0\n",
       "\"aapl.us.txt\"  1984-09-17  0.45718  0.46357  0.45718  0.45718  53755262  0\n",
       "\"aapl.us.txt\"  1984-09-18  0.45718  0.46103  0.44052  0.44052  27136886  0\n",
       "\"aapl.us.txt\"  1984-09-19  0.44052  0.44566  0.43157  0.43157  29641922  0\n",
       "\"aapl.us.txt\"  1984-09-20  0.43286  0.43668  0.43286  0.43286  18453585  0\n",
       "\"aapl.us.txt\"  1984-09-21  0.43286  0.44566  0.42388  0.42902  27842780  0\n",
       "\"aapl.us.txt\"  1984-09-24  0.42902  0.43157  0.42516  0.42516  22033109  0\n",
       "⋮\n",
       "\"tsla.us.txt\"  2017-10-27  319.75   324.59   316.66   320.87   6970118   0\n",
       "\"tsla.us.txt\"  2017-10-30  319.18   323.78   317.25   320.08   4254378   0\n",
       "\"tsla.us.txt\"  2017-10-31  320.23   331.95   320.18   331.53   5672347   0\n",
       "\"tsla.us.txt\"  2017-11-01  332.25   332.609  320.26   321.08   8457336   0\n",
       "\"tsla.us.txt\"  2017-11-02  300.13   308.69   292.63   299.26   19791416  0\n",
       "\"tsla.us.txt\"  2017-11-03  299.5    306.25   295.13   306.09   8893974   0\n",
       "\"tsla.us.txt\"  2017-11-06  307.0    307.5    299.01   302.78   6482486   0\n",
       "\"tsla.us.txt\"  2017-11-07  301.02   306.5    300.03   306.05   5286320   0\n",
       "\"tsla.us.txt\"  2017-11-08  305.5    306.89   301.3    304.31   4725510   0\n",
       "\"tsla.us.txt\"  2017-11-09  302.5    304.46   296.3    302.99   5440335   0\n",
       "\"tsla.us.txt\"  2017-11-10  302.5    308.36   301.85   302.99   4621912   0"
      ]
     },
     "execution_count": 1,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "using JuliaDB\n",
    "\n",
    "# Print table rather than column summary\n",
    "IndexedTables.set_show_compact!(false)\n",
    "\n",
    "# loadtable(\"stocksample\"; filenamecol = :Ticker, indexcols = [:Ticker, :Date]);\n",
    "t = load(\"stocks.jdb\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Return a Subset of Columns: \n",
    "\n",
    "- We can use `select` to return a selector (introduced in the previous notebook) applied to a table.\n",
    "\n",
    "## `select(table, selection)`\n",
    "\n",
    "- When multiple selectors are involved, rows are \"passed around\" as a `NamedTuple`.\n",
    "- A function paired with multiple selections must then accept a `NamedTuple`.\n",
    "\n",
    "- For example, to calculate the range of stock prices for each day we can:\n",
    "  1. Select `:High` and `:Low`\n",
    "  1. Pair it with the anonymous function `row -> row.High - row.Low`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "56023-element Array{Float64,1}:\n",
       "  0.01028\n",
       "  0.0115 \n",
       "  0.01152\n",
       "  0.01539\n",
       "  0.00125\n",
       "  0.01537\n",
       "  0.00639\n",
       "  0.02051\n",
       "  0.01409\n",
       "  0.00382\n",
       "  0.02178\n",
       "  0.00641\n",
       "  0.0077 \n",
       "  ⋮      \n",
       "  7.03   \n",
       "  7.93   \n",
       "  6.53   \n",
       " 11.77   \n",
       " 12.349  \n",
       " 16.06   \n",
       " 11.12   \n",
       "  8.49   \n",
       "  6.47   \n",
       "  5.59   \n",
       "  8.16   \n",
       "  6.51   "
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "select(t, (:High, :Low) => row -> row.High - row.Low)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Return a Subset of Rows:\n",
    "\n",
    "- We can get the rows that satisfy some condition (when a function returns true) with the syntax:\n",
    "\n",
    "## `filter(function, table; selection)` \n",
    "\n",
    "- Here we retrieve the data for AMZN (Amazon) by getting the rows for which `Ticker == \"amzn.us.txt\"`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Table with 5153 rows, 8 columns:\n",
       "\u001b[1mTicker         \u001b[22m\u001b[1mDate        \u001b[22mOpen     High     Low      Close    Volume    OpenInt\n",
       "────────────────────────────────────────────────────────────────────────────────\n",
       "\"amzn.us.txt\"  1997-05-16  1.97     1.98     1.71     1.73     14700000  0\n",
       "\"amzn.us.txt\"  1997-05-19  1.76     1.77     1.62     1.71     6106800   0\n",
       "\"amzn.us.txt\"  1997-05-20  1.73     1.75     1.64     1.64     5467200   0\n",
       "\"amzn.us.txt\"  1997-05-21  1.64     1.65     1.38     1.43     18853200  0\n",
       "\"amzn.us.txt\"  1997-05-22  1.44     1.45     1.31     1.4      11776800  0\n",
       "\"amzn.us.txt\"  1997-05-23  1.41     1.52     1.33     1.5      15937200  0\n",
       "\"amzn.us.txt\"  1997-05-27  1.51     1.65     1.46     1.58     8697600   0\n",
       "\"amzn.us.txt\"  1997-05-28  1.62     1.64     1.53     1.53     4574400   0\n",
       "\"amzn.us.txt\"  1997-05-29  1.54     1.54     1.48     1.51     3472800   0\n",
       "\"amzn.us.txt\"  1997-05-30  1.5      1.51     1.48     1.5      2594400   0\n",
       "\"amzn.us.txt\"  1997-06-02  1.51     1.53     1.5      1.51     591600    0\n",
       "\"amzn.us.txt\"  1997-06-03  1.53     1.53     1.48     1.48     1183200   0\n",
       "⋮\n",
       "\"amzn.us.txt\"  2017-10-27  1057.01  1105.58  1050.55  1100.95  16552598  0\n",
       "\"amzn.us.txt\"  2017-10-30  1095.01  1122.79  1093.56  1110.85  6613064   0\n",
       "\"amzn.us.txt\"  2017-10-31  1109.0   1110.54  1101.12  1105.28  3476967   0\n",
       "\"amzn.us.txt\"  2017-11-01  1105.4   1108.97  1096.74  1103.68  3755511   0\n",
       "\"amzn.us.txt\"  2017-11-02  1097.81  1101.94  1086.87  1094.22  3684876   0\n",
       "\"amzn.us.txt\"  2017-11-03  1091.15  1112.68  1088.52  1111.6   3751480   0\n",
       "\"amzn.us.txt\"  2017-11-06  1109.15  1125.41  1108.77  1120.66  3331738   0\n",
       "\"amzn.us.txt\"  2017-11-07  1124.74  1130.6   1117.5   1123.17  2684443   0\n",
       "\"amzn.us.txt\"  2017-11-08  1122.82  1135.54  1119.11  1132.88  2576010   0\n",
       "\"amzn.us.txt\"  2017-11-09  1125.96  1129.62  1115.77  1129.13  3729978   0\n",
       "\"amzn.us.txt\"  2017-11-10  1126.1   1131.75  1124.06  1125.35  2179181   0"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "filter(x -> x == \"amzn.us.txt\", t; select = :Ticker)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Apply a Function to a Selection:\n",
    "\n",
    "- We can use `map` to apply a function on a selection of a table with the syntax below:\n",
    "\n",
    "## `map(function, table; select)`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- If `select` is not provided, each full row will be passed to the function.  \n",
    "- Here we return the first item in each row:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "56023-element Array{String,1}:\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " ⋮            \n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\""
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "map(first, t)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "- Note that `map` and `select` can often be used to produce the same result since selections can be paired with a function.  \n",
    "- For example, we previously used \n",
    "\n",
    "    ```julia\n",
    "    select(t, (:High, :Low) => row -> row.High - row.Low)\n",
    "    ```\n",
    "\n",
    "    to calculate stock price ranges.  Equivalently, we can use:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "56023-element Array{Float64,1}:\n",
       "  0.00514\n",
       "  0.00382\n",
       "  0.00766\n",
       "  0.01539\n",
       "  0.00125\n",
       "  0.01023\n",
       "  0.00639\n",
       "  0.02051\n",
       "  0.01409\n",
       "  0.00382\n",
       "  0.01664\n",
       "  0.00641\n",
       "  0.0077 \n",
       "  ⋮      \n",
       "  4.06   \n",
       "  3.72   \n",
       "  3.7    \n",
       "  0.42   \n",
       " 11.529  \n",
       "  9.43   \n",
       "  0.16   \n",
       "  4.72   \n",
       "  0.45   \n",
       "  2.58   \n",
       "  1.47   \n",
       "  5.37   "
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "map(r -> r.High - r.Close, t)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# `reduce`\n",
    "\n",
    "- `reduce` applies a function (`reducer`) pair-wise to a selection through the syntax:\n",
    "\n",
    "## `reduce(reducer, table; select)`\n",
    "\n",
    "- For example, if a table is four rows long, `reduce(reducer, t)` is equivalent to\n",
    "\n",
    "```julia\n",
    "out = reducer(row1, row2)\n",
    "out = reducer(out, row3)\n",
    "out = reducer(out, row4)\n",
    "```\n",
    "\n",
    "- In order to be meaningful, the `reducer` must have the associative property:\n",
    "\n",
    "$$(A + B) + C = A + (B + C)$$\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1830996051150"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "reduce(+, t; select = :Volume)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can also `reduce` with estimators from **OnlineStats** (more on this later):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Sum: n=56023 | value=1830996051150"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "using OnlineStats\n",
    "\n",
    "reduce(Sum(Int), t; select = :Volume)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# `groupreduce`\n",
    "\n",
    "- Like `reduce`, `groupreduce` applies a reducer pair-wise to table elements.  \n",
    "- However, the reducer is applied separately across groups (unique values of another selection).  \n",
    "- The syntax is:\n",
    "\n",
    "## `groupreduce(reducer, table, by; selection)`\n",
    "\n",
    "- For example, we can find the total number of trades for each stock by calculating the sum of `:Volume`, grouped by `:Ticker`:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Table with 8 rows, 2 columns:\n",
       "\u001b[1mTicker          \u001b[22m+\n",
       "────────────────────────────\n",
       "\"aapl.us.txt\"   891950579821\n",
       "\"amzn.us.txt\"   40385735209\n",
       "\"dis.us.txt\"    85815802336\n",
       "\"googl.us.txt\"  26503128932\n",
       "\"ibm.us.txt\"    81302723803\n",
       "\"msft.us.txt\"   634313240042\n",
       "\"nflx.us.txt\"   62518969374\n",
       "\"tsla.us.txt\"   8205871633"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "groupreduce(+, t, :Ticker; select = :Volume)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# `groupby`\n",
    "\n",
    "- `groupby` applies a function to each group subset (not pair-wise like `reduce`) through the syntax:\n",
    "\n",
    "## `groupby(function, table [, by]; select)`\n",
    "\n",
    "- Here we get the mean and standard deviation of closing price for each stock:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Table with 8 rows, 3 columns:\n",
       "\u001b[1mTicker          \u001b[22mmean     std\n",
       "────────────────────────────────\n",
       "\"aapl.us.txt\"   22.281   37.7645\n",
       "\"amzn.us.txt\"   181.769  239.548\n",
       "\"dis.us.txt\"    20.6212  26.4787\n",
       "\"googl.us.txt\"  389.856  235.102\n",
       "\"ibm.us.txt\"    48.5542  49.2977\n",
       "\"msft.us.txt\"   18.9847  16.424\n",
       "\"nflx.us.txt\"   39.5213  47.5733\n",
       "\"tsla.us.txt\"   150.355  107.024"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "groupby((mean, std), t, :Ticker; select = :Close)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# `summarize`\n",
    "\n",
    "- `summarize` applies a function (or functions) column-wise.  The syntax is:\n",
    "\n",
    "## `summarize(function, table, by; select)`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Table with 8 rows, 5 columns:\n",
       "\u001b[1mTicker          \u001b[22mOpen_mean  Close_mean  Open_std  Close_std\n",
       "──────────────────────────────────────────────────────────\n",
       "\"aapl.us.txt\"   22.2844    22.281      37.7634   37.7645\n",
       "\"amzn.us.txt\"   181.747    181.769     239.611   239.548\n",
       "\"dis.us.txt\"    20.6162    20.6212     26.4788   26.4787\n",
       "\"googl.us.txt\"  389.993    389.856     235.105   235.102\n",
       "\"ibm.us.txt\"    48.5355    48.5542     49.271    49.2977\n",
       "\"msft.us.txt\"   18.9779    18.9847     16.4161   16.424\n",
       "\"nflx.us.txt\"   39.5034    39.5213     47.5678   47.5733\n",
       "\"tsla.us.txt\"   150.39     150.355     107.072   107.024"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "summarize((mean, std), t, :Ticker; select = (:Open, :Close))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# AoS and SoA\n",
    "\n",
    "- We can retrieve the table as a \"struct of arrays\" (`NamedTuple` of `Vector`s) or as an \"array of structs\" (`Vector` of `NamedTuple`s) via `columns` and `rows`, respectively.\n",
    "\n",
    "## `columns(t; selection)`\n",
    "\n",
    "## `rows(t; selection)`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "56023-element Array{String,1}:\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " \"aapl.us.txt\"\n",
       " ⋮            \n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\"\n",
       " \"tsla.us.txt\""
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# NamedTuple of Vectors\n",
    "columns(t)[1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(Ticker = \"aapl.us.txt\", Date = 1984-09-07, Open = 0.42388, High = 0.42902, Low = 0.41874, Close = 0.42388, Volume = 23220030, OpenInt = 0)"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Vector of NamedTuples\n",
    "rows(t)[1]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Joins\n",
    "\n",
    "## `join(left, right; how, <options>)`\n",
    "\n",
    "Join tables together based on matching keys.\n",
    "\n",
    "- `how` can be one of `:inner`, `:left`, `:outer`, or`:anti`\n",
    "- `<options>`: `rkey`, `lkey` (default to indexed variable), `rselect`, `lselect`"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Table with 5 rows, 2 columns:\n",
       "\u001b[1mx  \u001b[22my\n",
       "────────────\n",
       "1  0.598867\n",
       "2  0.880299\n",
       "3  0.0651531\n",
       "4  0.961551\n",
       "5  0.499147"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t1 = table(@NT(x=1:5, y = rand(5)); pkey = :x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Table with 5 rows, 2 columns:\n",
       "\u001b[1mx  \u001b[22mz\n",
       "───────────\n",
       "3  0.506358\n",
       "4  0.215028\n",
       "5  0.925266\n",
       "6  0.680365\n",
       "7  0.25632"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t2 = table(@NT(x=3:7, z = rand(5)); pkey = :x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Table with 3 rows, 3 columns:\n",
       "\u001b[1mx  \u001b[22my          z\n",
       "──────────────────────\n",
       "3  0.0651531  0.506358\n",
       "4  0.961551   0.215028\n",
       "5  0.499147   0.925266"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# try :inner, :outer, :left\n",
    "tjoin = join(t1, t2; how = :inner)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Merging\n",
    "\n",
    "- A `merge` results in a table that is still ordered by the primary key(s)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Table with 10 rows, 2 columns:\n",
       "\u001b[1mx   \u001b[22my\n",
       "─────────────\n",
       "1   0.598867\n",
       "2   0.880299\n",
       "3   0.0651531\n",
       "4   0.961551\n",
       "5   0.499147\n",
       "11  -0.476002\n",
       "12  0.862928\n",
       "13  -0.37055\n",
       "14  0.0595302\n",
       "15  0.708924"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "t3 = table(@NT(x=11:15, y = randn(5)), pkey = :x)\n",
    "\n",
    "merge(t1, t3)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Julia 0.6.2-pre",
   "language": "julia",
   "name": "julia-0.6"
  },
  "language_info": {
   "file_extension": ".jl",
   "mimetype": "application/julia",
   "name": "julia",
   "version": "0.6.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
